﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Text;
using System.Threading.Tasks;

namespace NodeBasedSkillEditor
{
    public class RT_Port
    {
        public enum EWorkingDirection
        {
            Foreward,   // FlowPort
            Backward    // Value Port
        }

        public EPortIOType IOType = EPortIOType.Unknown;
        public RT_Node ParentNode { get; private set; }
        public uint LocalId { get; private set; }
        public uint Id { get; private set; }
        public virtual EWorkingDirection WorkDirection => EWorkingDirection.Foreward;
        public virtual bool IsValuePort => false;
        public virtual bool IsListPort => false;

        public Func<DAG_Executor, AValue> OnGetValue;
        public Func<DAG_Executor, List<AValue>> OnGetValueList;

        /// <summary>
        /// FlowPort正向，ValuePort逆向，均只有一个有效的目标端口
        /// </summary>
        public RT_Port LinkedPortInWorkingDirection;

        public RT_Port(EPortIOType ioType, BasePort portData, RT_Node parentNode)
        {
            IOType = ioType;
            ParentNode = parentNode;
            LocalId = portData.PortLocalId;
            Id = DAGHelper.PortLocalId_To_PortGlobalId(parentNode.Id, portData.PortLocalId);
            ParentNode.AllPorts.Add(LocalId, this);
        }

        public virtual AValue GetValue(DAG_Executor executor)
        {
            return null;
        }

        public virtual List<AValue> GetValueList(DAG_Executor executor)
        {
            return null;
        }
    }

    public class RT_FlowPort : RT_Port
    {
        public RT_FlowPort(EPortIOType ioType, BasePort portData, RT_Node parentNode)
            : base(ioType, portData, parentNode)
        {
        }
    }

    public abstract class RT_ValuePort : RT_Port
    {
        protected RT_ValuePort(EPortIOType ioType, BasePort portData, RT_Node parentNode)
            : base(ioType, portData, parentNode)
        {
        }

        public override EWorkingDirection WorkDirection => EWorkingDirection.Backward;
        public override bool IsValuePort => true;
    }

    public class RT_SingleValuePort : RT_ValuePort
    {
        public AValue SourceValue { get; private set; }

        /// <summary>
        /// 作为Output Port时Value数值无意义
        /// </summary>
        /// <param name="ioType"></param>
        /// <param name="srcPortData"></param>
        public RT_SingleValuePort(EPortIOType ioType, BasePort srcPortData, RT_Node parentNode)
            : base(ioType, srcPortData, parentNode)
        {
            SourceValue = AValue.Factory(srcPortData as ValuePort);
        }

        public override AValue GetValue(DAG_Executor executor)
        {
            if (IOType == EPortIOType.Input)
            {
                if (LinkedPortInWorkingDirection != null)
                {
                    return LinkedPortInWorkingDirection.GetValue(executor);
                }
                else
                {
                    return SourceValue;
                }
            }
            else if (IOType == EPortIOType.Output)
            {
                return OnGetValue?.Invoke(executor);
            }
            return null;
        }

    }

    public class RT_ValueListPort : RT_ValuePort
    {
        public override bool IsListPort => true;

        public RT_ValueListPort(EPortIOType ioType, BasePort srcPortData, RT_Node parentNode)
            : base(ioType, srcPortData, parentNode)
        {

        }

        public override List<AValue> GetValueList(DAG_Executor executor)
        {
            if (IOType == EPortIOType.Input)
            {
                if (LinkedPortInWorkingDirection != null)
                {
                    return LinkedPortInWorkingDirection.GetValueList(executor);
                }
            }
            else if (IOType == EPortIOType.Output)
            {
                return OnGetValueList?.Invoke(executor);
            }
            return null;
        }
    }

}
